<?php
// +----------------------------------------------------------------------
// | ZengCMS [ 火火 ]
// +----------------------------------------------------------------------
// | Copyright (c) 2018 http://zengcms.com All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
// +----------------------------------------------------------------------
// | Author: 火火 <zengcms@qq.com>
// +----------------------------------------------------------------------

// +----------------------------------------------------------------------
// | 采集控制器
// +----------------------------------------------------------------------
namespace app\admin\controller\cms;

use tree\Tree;
use \QL\QueryList;
use think\facade\Db;
use think\facade\View;
use imagetool\ImageTool;
use app\admin\controller\Base;
use tcwei\smallTools\GetImgSrc;
use app\common\annotation\NodeAnotation;
use app\common\annotation\ControllerAnnotation;
use app\admin\model\cms\Document as DocumentModel;
use app\admin\model\Attachment as Attachment_Model;
/**
 * @ControllerAnnotation(title="采集管理")
 * Class Collection
 * @package app\admin\controller\cms
 */
class Collection extends Base
{
    /**
     * [initialize 初始化方法]
     * @return void
     */
    protected function initialize()
    {
        // 判断插件是否安装
        $addonInfo = getAddonInfo('collection');
        if(!$addonInfo || !$addonInfo['status']){
            $this->error($addonInfo?'插件已禁用！':'插件未安装！');
        }
        include_once ADDONS_PATH . '/collection/library/querylist/vendor/autoload.php';
        include_once ADDONS_PATH . '/collection/library/imgsrc/vendor/autoload.php';
        parent::initialize();
    }
    /**
     * @NodeAnotation(title="采集管理")
     */
    public function node_list()
    {
        $map = array();
        $query = array();
        $model_id = trim(input('model_id'));
        $status = trim(input('status'));
        $title = trim(input('title'));
        if ($model_id !== '' && is_numeric($model_id)) {
            $map[] = ['model_id', '=', $model_id];
            $query['model_id'] = $model_id;
        }
        if ($status !== '' && ($status == 0 || $status == 1)) {
            $map[] = ['n.status', '=', $status];
            $query['status'] = $status;
        }
        if ($title) {
            $map[] = ['n.node_name', 'like', "%$title%"];
            $query['title'] = $title;
        }
        $order = ['n.sort' => 'desc', 'n.id' => 'desc'];
        $list = Db::name('node')
        ->field('n.*,m.title')
        ->alias('n')
        ->LeftJoin("model m", "n.model_id=m.id")
        ->where($map)
        ->order($order)
        ->paginate(['list_rows'=> sys_config('WEB_ONE_PAGE_NUMBER'),'var_page' => 'page','query' => $query])
        ->each(function ($item, $key) {
            int_to_string($item, array('status' => array('0' => '隐藏', '1' => '显示')));
            return $item;
        });
        $modelRes = Db::name('model')->field('id,title')->where('form',0)->select()->toArray();
        View::assign([
            'meta_title' => '采集节点列表',
            'status' => $status,//状态
            'model_id' => $model_id,//模型id搜索条件
            'list' => $list,//列表
            'modelRes' => $modelRes,//所有模型信息
        ]);
        return view();
    } 
    /**
     * @NodeAnotation(title="添加列表页采集节点配置")
     */
    public function add_list_rules()
    {
        if (request()->isPost()) {
            $_data = input('post.');
            $validate = \think\facade\Validate::rule([
                'node_name' => 'require|max:64',
                'model_id' => 'require|number',
                'list_url' => 'require',
                'start_page' => 'require|number',
                'end_page' => 'require|number',
                'step' => 'require|number',
                'range' => 'require',
                'url' => 'require',
            ])->message([
                'node_name.require' => '节点名称必须填写',
                'node_name.max' => '节点名称最多不能超过64个字符',
                'model_id.require' => '所属模型必须选择',
                'model_id.number' => '所属模型选择有误',
                'list_url.require' => '列表URL必须填写',
                'start_page.require' => '起始页码必须填写',
                'start_page.number' => '起始页码必须是数字',
                'end_page.require' => '结束页码必须填写',
                'end_page.number' => '结束页码必须是数字',
                'step.require' => '步长必须填写',
                'step.number' => '步长必须是数字',
                'url.require' => 'URL采集规则必须填写',
            ]);
            if (!$validate->check($_data)) {
                $this->error($validate->getError());
            }
            $data['node_name'] = $_data['node_name'];
            $data['model_id'] = $_data['model_id'];
            $data['output_encoding'] = $_data['output_encoding'];
            $data['input_encoding'] = $_data['input_encoding'];
            $data['list_rules'] = array(
                'list_url' => $_data['list_url'],//列表URL
                'start_page' => $_data['start_page'],//页码配置-起始页码
                'end_page' => $_data['end_page'],//页码配置-结束页码
                'step' => $_data['step'],//页码配置-步长
                'range' => $_data['range'],//采集范围(区域选择器)
                'list_rules' => array(
                    'url' => $_data['url'],//URL采集规则
                    'litpic' => $_data['litpic'],//缩略图采集规则
                ),
            );
            $data['list_rules'] = json_encode($data['list_rules']);
            $data['thumb_field'] = $_data['thumb_field'];//所选模型的缩略图字段名称
            $data['down_attachment'] = $_data['down_attachment'];//是否下载图片
            $data['watermark'] = $_data['watermark'];//是否图片加水印
            $data['create_time'] = time();
            $data['update_time'] = time();
            $id = Db::name('node')->strict(false)->insertGetId($data);
            if ($id) {
                $this->success('添加采集节点-列表采集配置-成功', (string)url('add_item_rules', ['model_id' => $data['model_id'], 'node_id' => $id]));
            } else {
                $this->error('添加节点失败！');
            }
            return;
        }
        $modelRes = Db::name('model')->field('id,title')
        ->where([['form','=',0],['status','=',1]])
        ->select()->toArray();
        View::assign([
            'meta_title' => '添加采集节点-列表采集配置',
            'modelRes' => $modelRes,//所有模型信息
        ]);
        return view();
    } 
    /**
     * @NodeAnotation(title="添加内容页采集节点配置")
     */
    public function add_item_rules()
    {
        $model_id = input('model_id');
        $node_id = input('node_id');
        if (request()->isPost()) {
            $data = input('post.');
            unset($data['node_id']);
            $rules = array();
            if ($data) {
                foreach ($data as $k => $v) {
                    $rules[$k][0] = $v[0];
                    $rules[$k][1] = $v[1];
                    $rules[$k][2] = $v[2];
                    // $rules[$k]=array_values($rules[$k]);
                }
            }
            $rules = json_encode($rules);
            $save = Db::name('node')->where('id',$node_id)->update(['item_rules' => $rules]);
            if ($save) {
                action_log($node_id, 'node', 1);//记录新增行为
                $this->success('添加节点成功！', (string)url('node_list'));
            } else {
                $this->error('添加节点失败！');
            }
        }
        // 获取自定义模型字段
        $modelFieldRes = get_model_attribute($model_id,false);
        // 不要的字段
        $not_field = ['id', 'category_id', 'uid', 'status'];
        foreach ($modelFieldRes as $k => $v) {
            if (in_array($v['name'], $not_field) || $v['status'] == 0) {
                unset($modelFieldRes[$k]);
            }
        }
        View::assign([
            'meta_title' => '添加采集节点-内容采集配置',
            'modelFieldRes' => $modelFieldRes,
        ]);
        return view();
    } 
    /**
     * @NodeAnotation(title="编辑")
     */
    public function edit($id)
    {
        if (request()->isPost()) {
            $data = input('post.');
            $validate = \think\facade\Validate::rule([
                'node_name' => 'require|max:64',
                'model_id' => 'require|number',
                'list_url' => 'require',
                'start_page' => 'require|number',
                'end_page' => 'require|number',
                'step' => 'require|number',
                'range' => 'require',
                'url' => 'require',
            ])->message([
                'node_name.require' => '节点名称必须填写',
                'node_name.max' => '节点名称最多不能超过64个字符',
                'model_id.require' => '所属模型必须选择',
                'model_id.number' => '所属模型选择有误',
                'list_url.require' => '列表URL必须填写',
                'start_page.require' => '起始页码必须填写',
                'start_page.number' => '起始页码必须是数字',
                'end_page.require' => '结束页码必须填写',
                'end_page.number' => '结束页码必须是数字',
                'step.require' => '步长必须填写',
                'step.number' => '步长必须是数字',
                'url.require' => 'URL采集规则必须填写',
            ]);
            if (!$validate->check($data)) {
                $this->error($validate->getError());
            }
            $base = [];
            $base['id'] = $data['id'];
            $base['node_name'] = $data['node_name'];
            $base['model_id'] = $data['model_id'];
            $base['output_encoding'] = $data['output_encoding'];
            $base['input_encoding'] = $data['input_encoding'];
            $base['list_rules']['list_url'] = $data['list_url'];
            $base['list_rules']['start_page'] = $data['start_page'];
            $base['list_rules']['end_page'] = $data['end_page'];
            $base['list_rules']['step'] = $data['step'];
            $base['list_rules']['range'] = $data['range'];
            $base['list_rules']['list_rules']['url'] = $data['url'];
            $base['list_rules']['list_rules']['litpic'] = $data['litpic'];
            $base['list_rules'] = json_encode($base['list_rules']);
            $base['status'] = $data['status'];
            $base['sort'] = $data['sort'];
            $base['thumb_field'] = $data['thumb_field'];
            $base['down_attachment'] = $data['down_attachment'];
            $base['watermark'] = $data['watermark'];
            $base['update_time'] = time();
            $arr = array('id', 'node_name', 'model_id', 'output_encoding', 'input_encoding', 'list_url', 'start_page', 'end_page', 'step', 'range', 'url', 'litpic', 'thumb_field' ,'down_attachment','watermark','status', 'sort', 'update_time');
            foreach ($data as $k => $v) {
                if (in_array($k, $arr)) {
                    unset($data[$k]);
                }
            }
            $base['item_rules'] = json_encode($data);
            action_log($base['id'], 'node', 2);//记录修改前行为
            $save = Db::name('node')->strict(false)->update($base);
            if ($save !== false) {
                action_log($base['id'], 'node', 2);//记录修改后行为
                if ($save !== 0) {
                    $this->success('修改节点成功！', (string)url('node_list'));
                } else {
                    $this->error('未做修改！');
                }
            } else {
                $this->error('修改节点失败！');
            }
        }
        $node = Db::name('node')->find($id);
        $model_id = $node['model_id'];
        $listRules = json_decode($node['list_rules'], true);
        $_itemRules = json_decode($node['item_rules'], true);
        $modelRes = Db::name('model')->field('id,title')
        ->where([['form','=',0],['status','=',1]])
        ->select()->toArray();
        // 获取自定义模型字段
        $modelFieldRes = get_model_attribute($model_id,false);
        // 不要的字段
        $not_field = ['id', 'category_id', 'uid', 'status'];
        foreach ($modelFieldRes as $k => $v) {
            if (in_array($v['name'], $not_field) || $v['status'] == 0) {
                unset($modelFieldRes[$k]);
            }
        }
        // dump($modelFieldRes);dump($itemRules);
        // 下面判断是因为由于修改了模型字段或增加模型字段才执行的
        $itemRules = array();
        foreach ($modelFieldRes as $k => $v) {
            if (!isset($_itemRules[$v['name']])) { //模型新增的字段设置空
                $itemRules[$v['name']][0] = '';
                $itemRules[$v['name']][1] = '';
                $itemRules[$v['name']][2] = '';
            } else {
                $itemRules[$v['name']][0] = $_itemRules[$v['name']][0];
                $itemRules[$v['name']][1] = $_itemRules[$v['name']][1];
                $itemRules[$v['name']][2] = $_itemRules[$v['name']][2];
            }
        }
        // dump($modelFieldRes);dump($itemRules);die;
        View::assign([
            'meta_title' => '编辑采集节点',
            'id' => $id,//节点id
            'node' => $node,//当前节点信息
            'model_id' => $model_id,//当前模型id
            'modelRes' => $modelRes,//所有模型信息
            'modelFieldRes' => $modelFieldRes,//自定义模型字段
            'listRules' => $listRules,//列表规则
            'itemRules' => $itemRules,//内容规则
        ]);
        return view();
    } 
    /**
     * @NodeAnotation(title="状态")
     */
    public function setStatus($model = 'node', $data = array(), $type = 1)
    {
        $ids = input('ids');
        $status = input('status');
        $data['ids'] = $ids;
        $data['status'] = $status;
        return parent::setStatus($model, $data, $type);
    } 
    /**
     * @NodeAnotation(title="排序")
     */
    public function sort($model = 'node', $data = array())
    {
        $data['sort'] = input('sort');
        return parent::sort($model, $data);
    }
    /**
     * @NodeAnotation(title="删除")
     */
    public function del($ids = NULL)
    {
        $ids = !empty($ids) ? $ids : input('ids', 0);
        if (empty($ids)) {
            $this->error('参数不能为空！');
        }
        if (!is_array($ids)) {
            $ids = array(intval($ids));
        }
        foreach ($ids as $k => $v) {
            action_log($v,'node',3);
            Db::name('node')->delete($v);
            $html = Db::name('html')->field('id')->where('node_id',$v)->select()->toArray();
            foreach($html as $k2=>$v2){
                action_log($v2,'html',3);
                Db::name('html')->delete($v2);
            }
        }
        $this->success('删除采集节点成功！');
    }
    /**
     * @NodeAnotation(title="展示采集界面")
     */
    public function show()
    {
        $node_id = input('node_id');
        $model_id = input('model_id');
        $ids = input('ids','');
        $order = ['sort' => 'desc', 'id' => 'asc'];
        $map[] = ['model_id', '=', $model_id];
        $map[] = ['ispart', '=', 1];
        $allArctypeRes = Db::name('arctype')
        ->order($order)
        ->where($map)
        ->field('id,pid,typename')
        ->select()
        ->toArray();
        $tree = new Tree();
        $allArctypeRes = $tree->ChildrenTree($allArctypeRes, 0, 0);
        $node = Db::name('node')->field('node_name')->find($node_id);
        View::assign([
            'meta_title' => '开始采集',
            'node_id' => $node_id,
            'ids'=>$ids,
            'node_name' => $node['node_name'],
            'allArctypeRes' => $allArctypeRes,
        ]);
        return view();
    }
    /**
     * @NodeAnotation(title="执行采集")
     */
    public function do_caiji()
    {
        ini_set("max_execution_time", "0");//设置没有执行时间的限制
        ini_set('memory_limit', '-1');//设置内存不受限
        $node_id = input('node_id');//节点id
        $s = input('s');//步骤
        $curr = input('curr',1);//请求次数
        $node = Db::name('node')->find($node_id);//节点信息
        $outputEncoding = $node['output_encoding'];//输出编码
        $inputEncoding = $node['input_encoding'];//输入编码
        if($s == 1){ //步骤一列表页采集
            // 列表采集配置
            $listRules = $node['list_rules'];
            // json转换为数组
            $listRules = json_decode($listRules, true);
            // 采集列表网址
            $listUrl = $listRules['list_url'];
            // 采集开始页码
            $startPage = $listRules['start_page'];
            // 采集结束页码
            $endPage = $listRules['end_page'];
            // 页码步长
            $step = $listRules['step'];
            // 采集范围(区域选择器)
            $range = $listRules['range'];
            // 采集规则
            $listCaijiRules = $listRules['list_rules'];
            // 动态读取列表采集规则
            $listCaijiRules = array(
                'url' => array($listCaijiRules['url'], 'href'),
                'litpic' => array($listCaijiRules['litpic'], 'src'),
            );
            $_list_Url = [];
            // dump($listCaijiRules);die;
            // $listCaijiRules=array(
            //     "title"=>array('h2 a','text'),
            //     "url"=>array('h2 a','href'),
            // );
            // 处理采集列表网址
            for ($i = $startPage; $i <= $endPage; $i = $i + $step) {
                $_list_Url[] = str_replace('(*)', $i, $listUrl);
            }
            $page = 1;//每次采集的列表网址数
            $_listUrl = array_slice($_list_Url, ($curr - 1) * $page, $page);
            if(!$_listUrl){
                return json(['code'=>1,'s'=>2,'curr'=>1,'msg'=>'列表页采集完成！']);
            }
            // 循环采集列表数据
            $_data = [];
            foreach ($_listUrl as $k => $url) {
                $_data[] = QueryList::get($url, null, [
                    'headers' => [
                        'User-Agent' => 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.149 Safari/537.36',
                        'Accept-Encoding' => 'gzip, deflate, br',
                    ]
                ])->rules($listCaijiRules)
                ->encoding($outputEncoding, $inputEncoding)
                ->removeHead()
                ->range($range)
                ->queryData();
            }
            // dump($_data);die;
            // 数组重构，列表采集数据结果集
            $dataList = [];
            if(array_level($_data) == 3){
                foreach ($_data as $k => $v) {
                    foreach ($v as $k1 => $v1) {
                        $dataList[] = $v1;
                    }
                }
            }else{
                $dataList = $_data;
            }
            // dump($dataList);die;
            if($dataList){
                foreach($dataList as $k=>$v){
                    if(!Db::name('html')->where([['node_id','=',$node_id],['url','=',$v['url']]])->find()){
                        Db::name('html')->insert(['node_id'=>$node_id,'url'=>$v['url'],'litpic'=>$v['litpic'],'create_time'=>time()]);
                    }else{
                        Db::name('html')->where([['node_id','=',$node_id],['url','=',$v['url']]])->update(['litpic'=>$v['litpic']]);
                    }
                }
                return json(['code'=>1,'s'=>1,'curr'=>$curr+1,'msg'=>'列表页采集成功！']);
            }else{
                return json(['code'=>1,'s'=>2,'curr'=>1,'msg'=>'列表页采集完成！']);
            }
        }else if($s == 2){ //步骤二内容页采集
            // 内容页采集规则
            $itemRules = $node['item_rules'];
            // json转换数组
            $itemRules = json_decode($itemRules, true);
            // 内容数据采集结果集
            $limit = 1;//每页查询数
            $dataList = Db::name('html')->field('url,litpic')->where('node_id',$node_id)->order('sort desc')->page($curr,$limit)->select()->toArray();
            if(!$dataList){
                return json(['code'=>2,'msg'=>'采集完成！']);
            }
            $_dataItem = [];
            foreach ($dataList as $k => $v) {
                $_dataItem[] = QueryList::get($v['url'], null, [
                    'headers' => [
                        'User-Agent' => 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.149 Safari/537.36',
                        'Accept-Encoding' => 'gzip, deflate, br',
                    ]
                ])->rules($itemRules)
                ->encoding($outputEncoding, $inputEncoding)
                ->removeHead()
                ->range('')
                ->queryData();
                // $_dataItem[$k][0]['url'] = $v['url']; //手动添加url到数组，目的是写入临时表中
                // $_dataItem[$k][0]['litpic'] = $v['litpic']; //列表采集的缩略图
                $_dataItem[$k]['liturl'] = $v['url'];//手动添加url到数组，目的是写入临时表中
                if($node['thumb_field']){
                    $_dataItem[$k][$node['thumb_field']] = $v['litpic'];//列表采集的缩略图
                }else{
                    $_dataItem[$k]['litpic'] = $v['litpic'];//列表采集的缩略图
                }
            }
            // dump($_dataItem);die;
            // 数组重构
            $dataItem = [];
            if(array_level($_dataItem) == 3){
                foreach ($_dataItem as $k => $v) {
                    foreach ($v as $k1 => $v1) {
                        $dataItem[] = $v1;
                    }
                }
            }else{
                $dataItem = $_dataItem;
            }
            // dump($dataItem);die;
            // 将数据写入临时表
            foreach ($dataItem as $k => $v) {
                $data['node_id'] = $node_id;
                $data['title'] = $v['title'];
                $data['url'] = $v['liturl'];
                // $data['create_time'] = time();
                $reData = Db::name('html')->where('url',$v['liturl'])->find();
                unset($v['liturl']);
                unset($v['litpic']);
                $data['result'] = json_encode($v);
                if ($reData) {
                    Db::name('html')->where('url',$data['url'])->update($data);
                }else{
                    Db::name('html')->strict(false)->insert($data);
                }
            }
            // 节点最后采集时间
            Db::name('node')->where('id',$node_id)->update(['update_time' => time()]);
            return json(['code'=>1,'s'=>2,'curr'=>$curr + 1,'msg'=>'内容页采集成功！']);
        }
    } 
    /**
     * @NodeAnotation(title="导出数据到模型表")
     */
    public function export_data()
    {
        $node_id = input('node_id/d');
        $category_id = input('category_id');
        // 检查权限
        if(!$this->CheckPermissions($category_id,'add')){
            return json(['code'=>0,'msg'=>'该栏目您没有权限新增文档！']);
        }
        $ids = input('ids');
        if($ids){
            $map[] = ['id','in',explode('|',$ids)];
        }else{
            $map = array();
        }
        $node = Db::name('node')->find($node_id);
        $extend_id = Db::name('model')->where('id',$node['model_id'])->value('extend');
        $arctype = Db::name('arctype')->field('id,model_id')->find($category_id);
        $data = Db::name('html')
        ->field('id,url,status,result')
        ->where([['status','=',0],['node_id','=',$node_id]])
        ->where($map)
        ->limit(1)//每次导出1条数据
        ->select()
        ->toArray();
        if(!$data){
            return json(['code'=>2,'msg'=>'导出完成！']);
        }
        $i = 0;
        $DocumentModel = new DocumentModel();
        foreach ($data as $k => $v) {
            // 获取采集站点url信息
            $url_arr = parse_url($v['url']);
            if($url_arr['scheme']){
                $prefix_url = $url_arr['scheme']. '://'.$url_arr['host'];
            }else{
                $prefix_url = $url_arr['host'];
            }
            $_data = json_decode($v['result'], true);
            $_data['model_id'] = $arctype['model_id'];
            $_data['category_id'] = $arctype['id'];
            $_data['status'] = 0;
            if($extend_id){
                $where[] = ['model_id', 'in' ,[$extend_id, $node['model_id']]];
            }else{
                $where[] = ['model_id', '=' ,$node['model_id']];
            }
            foreach($_data as $k2=>$v2){
                if($v2){
                    $type = Db::name('attribute')
                    ->where($where)
                    ->where('name',$k2)
                    ->value('type');
                    $file_field = ['picture','piclist','file','filelist','onevideo','videolist'];
                    // 文件字段
                    if(in_array($type,$file_field)){ //图片字段的图片上传
                        // 判断采集的站点图片是否带http
                        if(strpos($v2,'http') === false){
                            $v2 = $prefix_url . '/' . trim($v2,'/');
                        }
                        if($node['down_attachment']){
                            $_data[$k2] = $this->download_file($v2,$node['watermark']);
                        }else{
                            $_data[$k2] = $v2;
                        }
                    }elseif(in_array($type,['kindeditor','ueditor'])){ //编辑器内容的图片上传
                        $src = new GetImgSrc();
                        // 找编辑器内容的图片
                        $imgArr = $src::srcList($v2,1);
                        foreach($imgArr as $k3=>$v3){
                            if(strpos($v3,'http') === false){
                                $v4 = $prefix_url . '/' . trim($v3,'/');
                            }else{
                                $v4 = $v3;
                            }
                            if($node['down_attachment']){
                                $url = get_file_url($this->download_file($v4,$node['watermark']));
                            }else{
                                $url = $v4;
                            }
                            $v2 = str_replace($v3,$url,$v2);
                        }
                        $_data[$k2] = $v2;
                    }
                }
            }
            try {   
                $result = $DocumentModel->add($_data);
            } catch (\Exception $e) {   
               return json(['code'=>0,'msg'=>'ID-'.$v['id'] . '错误：' . $e->getMessage()]);
            }
            if($result['code'] == 1){
                // 改为已导出
                Db::name('html')->where('id',$v['id'])->update(['status' => 1]);
            }else{
                return json(['code'=>0,'msg'=>'ID-'.$v['id'] . '错误：' . $result['msg']]);
            }
            $i++;
            // 每导入2条数据睡10毫秒
            /* if ($i % 2 == 0) {
                usleep(10000);
            } */
        }
        return json(['code'=>1,'msg'=>'导出成功！']);
    }
    /**
     * @NodeAnotation(title="采集数据列表")
     */
    public function data_list()
    {
        $map = array();
        $query = array();
        $node_id = input('node_id');
        $model_id = input('model_id');
        $map[] = ['node_id','=',$node_id];
        $query['node_id'] = $node_id;
        $status = trim(input('status'));
        $title = trim(input('title'));
        if ($status !== '' && ($status == 0 || $status == 1)) {
            $map[] = ['status', '=', $status];
            $query['status'] = $status;
        }
        if ($title) {
            $map[] = ['title|url', 'like', "%$title%"];
            $query['title'] = $title;
        }
        $order = ['sort' => 'desc', 'id' => 'desc'];
        $list = Db::name('html')
        ->field(true)
        ->where($map)
        ->order($order)
        ->paginate(['list_rows'=> sys_config('WEB_ONE_PAGE_NUMBER'),'var_page' => 'page','query' => $query])
        ->each(function ($item, $key) {
            int_to_string($item,array('status' => array('0' => '未导出', '1' => '已导出')));
            return $item;
        });
        View::assign([
            'meta_title' => '采集数据列表',
            'status' => $status,//状态
            'node_id'=>$node_id,//节点id
            'model_id'=>$model_id,//模型id
            'list' => $list,//列表
        ]);
        return view();
    }
    /**
     * @NodeAnotation(title="查看采集数据")
     */
    public function data_view()
    {
        if(request()->isPost()){
            $data = input('post.');
            $id = $data['id'];
            $title = $data['title'];
            unset($data['id']);
            $result = json_encode($data);
            $res = Db::name('html')->where('id',$id)->update(['title'=>$title,'result'=>$result]);
            if($res !== false){
                $this->success('更新成功！');
            }
            $this->error('更新失败！');
        }
        $id = input('id/d');
        $model_id = input('model_id/d');
        $info = Db::name('html')->find($id);
        $result = json_decode($info['result'],true);
        $data = [];
        $extend = get_document_model($model_id,'extend');
        if($extend){
            $map = [
                ['model_id','in',[$model_id,$extend]]
            ];
        }else{
            $map = [
                ['model_id','=',$model_id]
            ];
        }
        foreach($result as $k=>$v){
            $title = Db::name('attribute')->where('name',$k)->where($map)->value('title');
            if($title){
                $arr['name'] = $k;
                $arr['title'] = $title;
                $arr['value'] = $v;
                $data[] = $arr;
            }
        }
        View::assign([
            'meta_title'=>'查看采集数据',
            'id'=>$id,
            'info' => $data,
        ]);
        return view();
    }
    /**
     * @NodeAnotation(title="刪除采集数据")
     */
    public function data_del($ids = NULL)
    {
        $ids = !empty($ids) ? $ids : input('ids', 0);
        if (empty($ids)) {
            $this->error('参数不能为空！');
        }
        if (!is_array($ids)) {
            $ids = array(intval($ids));
        }
        foreach ($ids as $k => $v) {
            action_log($v,'html',3);
            Db::name('html')->delete($v);
        }
        $this->success('删除成功！');
    }
    // 下载文件
    protected function download_file($url, $watermark)
    {
        $url = trim(urldecode($url));
        $host = parse_url($url, PHP_URL_HOST);
        // 当前域名下的文件不下载
        if ($host != $_SERVER['HTTP_HOST']) {
            $fileExt = strrchr($url, '.');
            if (!in_array($fileExt, ['.jpg', '.gif', '.png', '.bmp', '.jpeg', '.tiff'])) {
                return '';
            }
            $filename = PROJECT_PATH . '/public/static/uploads/temp/' . md5($url) . $fileExt;
            if (http_down($url, $filename) !== false) {
                $file_info['md5'] = hash_file('md5', $filename);
                if ($file_exists = Attachment_Model::where(['md5' => $file_info['md5']])->find()) {
                    @unlink($filename);
                    return $file_exists['path'];
                } else {
                    // 图片水印
                    if($watermark && sys_config('WEB_ENABLE_WATER')){
                        $res = ImageTool::water($filename, $type = '', $water_img = '', $water_text = '', $text_size = '', $text_color = '', $water_tmd = '', $water_pos = '', $del = false);
                        if ($res['code']) {
                            // 删除原图
                            @unlink($filename);
                            $filename = STATIC_PATH . '/' . $res['path'];
                        }
                    }
                    $file_info['aid'] = UID;
                    $file_info['uid'] = 0;
                    $file_info['group_id']  = 0;
                    $file_info['sha1'] = hash_file('sha1', $filename);
                    $file_info['size'] = filesize($filename);
                    $file_info['mime'] = mime_content_type($filename);
                    $fpath =  'images/' . date('Ymd');
                    $savePath = PROJECT_PATH . '/public/static/uploads/' . $fpath;
                    if (!is_dir($savePath)) {
                        mkdir($savePath, 0755, true);
                    }
                    $fname = '/' . md5(microtime(true)) . $fileExt;
                    $file_info['file_name'] = basename($fname);
                    $file_info['file_type'] = get_attachment_info($filename)['type'];
                    $file_info['module'] = 'admin';
                    $file_info['name'] = basename($url);
                    $file_info['path'] = 'uploads/' . str_replace('\\', '/', $fpath . $fname);
                    $file_info['thumb'] = '';
                    $file_info['url'] = '';
                    $file_info['ext'] = ltrim($fileExt, ".");
                    $file_info['status'] = 1;
                    $file_info['sort'] = 100;
                    $file_info['create_time'] = time();
                    $file_info['update_time'] = time();
                    if (rename($filename, $savePath . $fname)) {
                        // 附件上传钩子，用于第三方文件上传扩展
                        if (sys_config('upload_driver','local') != 'local') {
                            $hook_result = hook('UploadOss', $file_info, false);
                            $arr = json_decode($hook_result,true);
                            if($arr['code'] != 0){
                                return $url;
                            }
                            return $arr['path'];
                            @unlink($savePath . $fname);
                        }else{
                            if (Attachment_Model::create($file_info)) {
                                return $file_info['path'];
                            }else{
                                return $url;
                            }
                        }
                    }
                }
            }else{
                return $url;
            }
        }else{
            return $url;
        }
    }
    // 检查权限
    protected function CheckPermissions($category_id,$action)
    {
        if(UID !== 1){
            $group_id_arr = Db::name('auth_group_access')->where('uid',UID)->column('group_id');
            $catidPrv = Db::name('arctype_priv')
            ->where([
                ['catid','=',$category_id],
                ['roleid','in',$group_id_arr],
                ['is_admin','=',1],
                ['action','=',$action],
            ])->find();
            if (empty($catidPrv)) {
                return false;
            }
            return true;
        }
        return true;
    }
    // 测试找html中图片链接
    // 高效率字符串模式（可比正则获取快3倍）从HTML或者文章内容等字符串中提取图片的src，可指定提取第几张图片、顺数第几或逆数第几、可指定黑名单等。
    public function test_imgsrc()
    {
        // GetImgSrc::src 单张获取(可比普通正则获取快3倍)
        // 获取HTML字符串中的图片地址 用法示例：
        // use tcwei\smallTools\GetImgSrc;
        // $htmlStr = '这里可以是新闻等文章或者html内容';
        //获取首张图片的src
        // $imgSrc = GetImgSrc::src($htmlStr, 1);
        /**
         * 提取HTML文章中的图片地址
         * @param string $data
         * @param int $num 第 $num 个图片的src，默认为第一张
         * @param string $order 顺取倒取； 默认为 asc ，从正方向计数。 desc 从反方向计数
         * @param string|array $blacklist 图片地址黑名单，排除图片地址中包含该数据的地址；例如 传入 baidu.com  会排除 src="http://www.baidu.com/img/a.png"
         * @param string $model 默认为字符串模式;可取值 string  preg；string模式处理效率高，PHP版本越高速度越快，可比正则快几倍
         * @return false | null | src  当data为空时返回 false ， src不存在时返回 null ，反之返回src
         */
        // public static function src($data = null, $num = 1, $order = 'asc', $blacklist = false, $model = 'string')
        // GetImgSrc::srcList 多张获取
        // 从第一张获取，共获取3张
        // $srcArr = GetImgSrc::srcList($htmlStr, 1, 3);
        // 参数解释：
        /**
        * 提取HTML文章中的图片地址
        * @param string $data HTML或者文章
        * @param int $startNum 默认为1，从第一张图片开始抽取
        * @param int $length 从 $startNum 开始抽取，共抽取 $length 张；默认为0，为0则抽取到最后
        * @param string $order 顺取倒取； 默认为 asc ，从正方向计数。 desc 从反方向计数
        * @param string|array $blacklist 图片地址黑名单，排除图片地址中包含该数据的地址；例如 传入 img.baidu.com  会排除 src="img.baidu.com/a.png"
        * @param string $model 抽取集合时，默认为正则模式；可选模式：preg  string，当 $length > 3 或者 $length = 0时，强制使用正则模式，因为取的数量大时，正则速度更快。
        * @return 图片地址的集合数组，若无则返回空数组[]
        */
        // public static function srcList($data, $startNum = 1, $length = 0, $order = 'asc', $blacklist = false, $model = 'preg')
        $html = '<div class="news_content">
        <section class="core">
            <p>路通智行与北京理工大学、加拿大阿尔伯塔大学、加拿大国家车联网技术研究院等科研机构展开多领域、全方位战略合作。专家团队由院士、长江学者、国千及众多国内外专家代表组成，在加拿大和硅谷分别设立了示范基地和技术研发中心。</p>
            <p><img src="/public/static/uploads/ueditor/image/20181212/1544608696.jpg" title="1544608696.jpg" _src="/public/static/uploads/ueditor/image/20181212/1544608696.jpg" alt="图片1.jpg"></p>
            <p><br></p>
            <p>研发团队着重于智能交通系统以及车联网的建模、算法、人工智能先进技术研究，在智能交通领域处于世界顶级水准。硅谷研发中心的研发重点包括自动驾驶、共享出行，人工智能等领域；依靠硅谷的创新环境，进行最新产品和技术的研发，同时将先进的车联网技术应用到前沿的场景中。</p>
            <p>&nbsp;</p>
            <p><img src="/public/static/uploads/ueditor/image/20181212/1544608846.jpg" title="1544608846.jpg" _src="/public/static/uploads/ueditor/image/20181212/1544608846.jpg" alt="333.jpg"></p>
            <p>技术专家已在智能交通、车联网、车路协同、交通控制与优化、交通信息感知与监控、智能公共交通、无线通信、云计算技术领域、无人驾驶等领域获得多项发明专利、著作权等。</p>
            <p><br></p>			    
            </section>
        </div>';
        $src = new \tcwei\smallTools\GetImgSrc();
        $img = $src::srcList($html,1);
        dump($img);die;
    }
}
